#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
    Copyright (c) 2007, Jiří Procházka
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    The author can be reached via e-mail to Pro.J@seznam.cz
"""

import os, copy, ConfigParser, tarfile, datetime, tempfile, shutil, traceback, subprocess

time = datetime.datetime #class for getting current time

def consist(fpath):
    """check if versions in the info file match the archive"""
    try:
        fname = os.path.split(os.path.abspath(fpath))[1]
        fdir = os.path.dirname(os.path.abspath(fpath))
        #reading version archive info file
        file1c = ConfigParser.ConfigParser()
        file1 = open(os.path.join(fdir,'.pyvcs',fname+'.pyvcs'))
        file1c.readfp(file1)
        file1.close()
        #getting a list of sections in the info file
        infolist = file1c.sections()
        #opening version archive file
        file2 = tarfile.open(os.path.join(fdir,'.pyvcs/',fname+'.tgz'), 'r:gz')
        #checking if all versions records in the info file have their counterpart in the archive
        for x in infolist:
            if x != 'Main':
               y =  file2.getmember(fname+'.'+x)
        #checking if the number of version records in the info file matches the number of versions in the archive
        if 'Main' in infolist:
            i = 1
        else:
            i = 0
        if len(file2.getnames()) != (len(infolist) - i):
            raise StandardError, 'the archive contains more files than the record file'
    except:
        err = traceback.format_exc()
        raise StandardError, 'Consistency check error:\n '+err

def expver(fpath, ftarget, version):
    """exports specified version of the archive"""
    version = str(version)
    fname = os.path.split(os.path.abspath(fpath))[1]
    fdir = os.path.dirname(os.path.abspath(fpath))
    #reading the version archive info file
    file1c = ConfigParser.ConfigParser()
    file1 = open(os.path.join(fdir,'.pyvcs/',fname+'.pyvcs'))
    file1c.readfp(file1)
    file1.close()
    #looking for the right version in the info file
    for verid in file1c.sections():
        if verid != 'Main':
            x = file1c.get(str(verid), 'version')
            if(x == version):
                #opening the archive and extracting to a temporary location
                file2 = tarfile.open(os.path.join(fdir,'.pyvcs/',fname+'.tgz'), 'r:gz')
                file2.extract(fname+"."+version)
                file2.close()
                #copying to the right location
                os.rename(fname+"."+version, ftarget)
                return 1
    #the for loop end when the right version wasn't found, so raise error
    raise StandardError, 'specified version wasn\'t found in the archive'

def addver(fpath, notes=''):
    """addds a specified file to the archive as new version"""
    fname = os.path.split(os.path.abspath(fpath))[1]
    fdir = os.path.dirname(os.path.abspath(fpath))
    #reading the version archive info file
    file1c = ConfigParser.ConfigParser()
    file1 = open(os.path.join(fdir,'.pyvcs/',fname+'.pyvcs'))
    file1c.readfp(file1)
    file1.close()
    #getting a list of version from the info file
    x = []
    for verid in file1c.sections():
        if verid != 'Main':
            x.append(int(file1c.get(str(verid), 'version')))
    x.sort()
    #getting number of version that will be added
    newver = int(x[-1])+1
    try:
        #opening the archive file
        file2 = tarfile.open(os.path.join(fdir,'.pyvcs/',fname+'.tgz'), 'r:gz')
        #create a temporary directory and extract there the archive
        tempdir = os.path.join(fdir,'.pyvcs/','tmp')
        os.mkdir(tempdir)
        filelist = file2.getnames()
        file2.extractall(tempdir)   
        file2.close()
        #opening the archive file for writing (erasing is)
        f2f = tarfile.open(os.path.join(fdir,'.pyvcs/',fname+'.tgz'), 'w:gz')
        #add old versions and the new one to the archive
        for i in filelist:
            f2f.add(os.path.join(tempdir,i), i)
        os.rename(os.path.abspath(fpath), os.path.abspath(fpath)+'.'+str(newver))
        f2f.add(os.path.abspath(fpath)+'.'+str(newver), fname+'.'+str(newver))
        f2f.close()
    finally:
        #cleanup - delete the temporary directory and rename the added file back
        shutil.rmtree(tempdir)
        os.rename(os.path.abspath(fpath)+'.'+str(newver), os.path.abspath(fpath))
    #add a record about the added version to the info file
    file1c.add_section(str(newver))
    file1c.set(str(newver), 'version', newver)
    file1c.set(str(newver), 'date', str(time.now()))
    file1c.set(str(newver), 'notes', notes)
    file11 = open(os.path.join(fdir,'.pyvcs/',fname+'.pyvcs'), 'w')
    file1c.write(file11)
    file11.close()
    
def newarch(fpath, notes=''):
    """create a new version archive"""
    fname = os.path.split(os.path.abspath(fpath))[1]
    fdir = os.path.dirname(os.path.abspath(fpath))
    #if directory PATH/pyvcs/ doesnt exist, create it
    if os.access(os.path.join(fdir,'.pyvcs/'), os.F_OK) == False:
        os.mkdir(os.path.join(fdir,'.pyvcs/'))
    #create the archive and add the 1st version to it
    try:
        f2f = tarfile.open(os.path.join(fdir,'.pyvcs/',fname+'.tgz'), 'w:gz')
        os.rename(os.path.abspath(fpath), os.path.abspath(fpath)+'.'+str(1))
        f2f.add(os.path.abspath(fpath)+'.'+str(1), fname+'.'+str(1))
        f2f.close()
    finally:
        os.rename(os.path.abspath(fpath)+'.'+str(1), os.path.abspath(fpath))
    #create the info file
    file1c = ConfigParser.ConfigParser()
    file1c.add_section('1')
    file1c.set('1', 'version', 1)
    file1c.set('1', 'date', str(time.now()))
    file1c.set('1', 'notes', notes)
    file1 = open(os.path.join(fdir,'.pyvcs/',fname+'.pyvcs'), 'w')
    file1c.write(file1)
    file1.close()

def diff(fpath, diffapp, rev1, rev2):
    """function for launching a diff aplication"""
    rev1 = int(rev1)
    rev2 = int(rev2)
    fname = os.path.split(os.path.abspath(fpath))[1]
    fdir = os.path.dirname(os.path.abspath(fpath))
    try:
        #extract desired versions to a temporary directory
        f = tarfile.open(os.path.join(fdir,'.pyvcs/',fname+'.tgz'), 'r:gz')
        f.extract(fname+'.'+str(rev1), os.path.join(fdir,'.pyvcs/','temp'))
        f.extract(fname+'.'+str(rev2), os.path.join(fdir,'.pyvcs/','temp'))
        #prepare a string for subprocess.call()
        difff = str(diffapp).split(' ')
        difff.append(os.path.join(fdir,'.pyvcs/','temp',fname+'.'+str(rev1)))
        difff.append(os.path.join(fdir,'.pyvcs/','temp',fname+'.'+str(rev2)))
        #run the diff application as subprocess
        subprocess.call(difff)
    finally:
        #cleanup - delete the temporary directory
        os.remove(os.path.join(fdir,'.pyvcs/','temp',fname+'.'+str(rev1)))
        os.remove(os.path.join(fdir,'.pyvcs/','temp',fname+'.'+str(rev2)))
        os.rmdir(os.path.join(fdir,'.pyvcs/','temp'))
